/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entidade.controller.JSF;

import entidade.controller.JPA.EntradaSaidaJpaController;
import entidade.controller.JPA.OperacaoExtraTipoJpaController;
import entidade.controller.JPA.OpercaoExtraJpaController;
import entidade.controller.JPA.ProdutoJpaController;
import entidade.controller.JPA.ProdutoVendaJpaController;
import entidade.controller.JPA.VendaJpaController;
import entidade.controller.JSF.util.PagingInfo;
import entidade.persistencia.Venda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import javax.faces.FacesException;
import entidade.controller.JSF.util.JsfUtil;
import entidade.controller.JPA.exceptions.NonexistentEntityException;
import entidade.controller.JPA.exceptions.IllegalOrphanException;
import entidade.persistencia.EntradaSaida;
import entidade.persistencia.OperacaoExtraTipo;
import entidade.persistencia.OpercaoExtra;
import entidade.persistencia.Produto;
import entidade.persistencia.ProdutoVenda;
import entidade.vo.ParcelaVO;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

/**
 *
 * @author victorinox
 */
public class VendaController {

    public VendaController() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        jpaController = (VendaJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "vendaJpa");
        pagingInfo = new PagingInfo();
        converter = new VendaConverter();
    }
    private Venda venda = null;
    private List<Venda> vendaItems = null;
    private VendaJpaController jpaController = null;
    private VendaConverter converter = null;
    private PagingInfo pagingInfo = null;
    private List<ParcelaVO> parcelaVenda = null;
    private Boolean isEditingVenda = false;
    private Integer qtdParcelas = 1;
    private OperacaoExtraTipo opDummy;

    public PagingInfo getPagingInfo() {
        if (pagingInfo.getItemCount() == -1) {
            pagingInfo.setItemCount(jpaController.getVendaCount());
            pagingInfo.setBatchSize(50);
        }
        return pagingInfo;
    }

    public SelectItem[] getVendaItemsAvailableSelectMany() {
        return JsfUtil.getSelectItems(jpaController.findVendaEntities(), false);
    }

    public SelectItem[] getVendaItemsAvailableSelectOne() {
        return JsfUtil.getSelectItems(jpaController.findVendaEntities(), true);
    }

    public Venda getVenda() {
        if (venda == null) {
            venda = (Venda) JsfUtil.getObjectFromRequestParameter("jsfcrud.currentVenda", converter, null);
        }
        if (venda == null) {
            venda = new Venda();
        }
        return venda;
    }

    public String listSetup() {
        reset(true);
        return "venda_list";
    }

    public String createSetup() {
        reset(false);
        venda = new Venda();
        return "venda_create";
    }

    public String voltarVendaSetup() {
        return "venda_create";
    }

    public OperacaoExtraTipo getOperacao() {

        if (opDummy == null) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            OperacaoExtraTipoJpaController opJPA = (OperacaoExtraTipoJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "operacaoExtraTipoJpa");
            List<OperacaoExtraTipo> opList = opJPA.findOperacaoExtraTipoEntities();
            for (Iterator<OperacaoExtraTipo> it = opList.iterator(); it.hasNext();) {
                OperacaoExtraTipo operacaoExtraTipo = it.next();
                return operacaoExtraTipo;
            }
        }
        return opDummy;
    }

    public void setOperacao(OperacaoExtraTipo op) {
    }

    public void addOperacaoExtraAction(ValueChangeEvent evt) {

        OperacaoExtraTipo newValue = (OperacaoExtraTipo) evt.getNewValue();
        if (newValue == null) {
            return;
        }
        OpercaoExtra op = new OpercaoExtra();
        op.setVendaId(venda);
        op.setValor(0.f);
        FacesContext facesContext = FacesContext.getCurrentInstance();
        OperacaoExtraTipoJpaController opJPA = (OperacaoExtraTipoJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "operacaoExtraTipoJpa");
        List<OperacaoExtraTipo> opList = opJPA.findOperacaoExtraTipoEntities();
        for (Iterator<OperacaoExtraTipo> it = opList.iterator(); it.hasNext();) {
            OperacaoExtraTipo operacaoExtraTipo = it.next();
            opDummy = operacaoExtraTipo;
            if (newValue.getNome().equalsIgnoreCase(operacaoExtraTipo.getNome())) {
                op.setOperacaoExtraTipoId(operacaoExtraTipo);
                List<OpercaoExtra> ops = venda.getOpercaoExtraCollection();
                boolean notFind = true;
                if (ops == null) {
                    ops = new ArrayList<OpercaoExtra>();
                }
                for (Iterator<OpercaoExtra> itop = ops.iterator(); itop.hasNext();) {
                    OpercaoExtra opercaoExtra = itop.next();
                    if (opercaoExtra.getOperacaoExtraTipoId().getOperacaoExtraTipoId().intValue() == operacaoExtraTipo.getOperacaoExtraTipoId().intValue()) {
                        notFind = false;
                    }
                }
                if (notFind) {
                    ops.add(op);
                    venda.setOpercaoExtraCollection(ops);
                }
            }
        }
    }

    public String create() {

        List<ProdutoVenda> pvs = venda.getProdutoVendaCollection();
        venda.setProdutoVendaCollection(null);
        List<OpercaoExtra> ops = venda.getOpercaoExtraCollection();
        venda.setOpercaoExtraCollection(null);

        try {

            jpaController.create(venda);

            FacesContext facesContext = FacesContext.getCurrentInstance();
            ProdutoVendaJpaController prodVendaController = (ProdutoVendaJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "produtoVendaJpa");
            ProdutoJpaController prodController = (ProdutoJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "produtoJpa");
            for (int i = 0; i < pvs.size(); i++) {
                ProdutoVenda prodVenda = pvs.get(i);

                Produto prod = prodVenda.getProduto();
                prod.setQuantidadeEstoque(prod.getQuantidadeEstoque() - prodVenda.getQuantidade());

                prodController.edit(prod);

                prodVenda.setVenda(venda);
                prodVendaController.create(prodVenda);
            }
            OpercaoExtraJpaController opExController = (OpercaoExtraJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "opercaoExtraJpa");
            for (Iterator<OpercaoExtra> it = ops.iterator(); it.hasNext();) {
                OpercaoExtra opercaoExtra = it.next();
                opercaoExtra.setVendaId(venda);
                opExController.create(opercaoExtra);
            }



            List<EntradaSaida> entradaSaidaList = new ArrayList<EntradaSaida>();
            EntradaSaidaJpaController entradaSaidaController = (EntradaSaidaJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "entradaSaidaJpa");
            List<Venda> vendasTemp = new ArrayList<Venda>();
            vendasTemp.add(venda);
            for (int i = 0; i < parcelaVenda.size(); i++) {
                ParcelaVO parcVenda = parcelaVenda.get(i);
                EntradaSaida entradaSaida = new EntradaSaida();
                entradaSaida.setDataOperacao(venda.getDataVenda());
                entradaSaida.setDataVencimento(parcVenda.getDataParcela());
                entradaSaida.setParcelaAtual(parcVenda.getNumeroParcela());
                entradaSaida.setQuantidadeParcela(parcVenda.getTotParcelas());
                entradaSaida.setValor(parcVenda.getValorParcela());
                entradaSaida.setVendaCollection(vendasTemp);
                entradaSaidaController.create(entradaSaida);
                entradaSaidaList.add(entradaSaida);
            }

            parcelaVenda = null;
            venda.setJurosMes(0f);
            qtdParcelas = 1;

            setIsEditingVenda(false);
            JsfUtil.addSuccessMessage("Venda was successfully created.");
        } catch (Exception e) {
            JsfUtil.ensureAddErrorMessage(e, "A persistence error occurred.");
            return null;
        }
        return listSetup();
    }

    public String detailSetup() {
        return scalarSetup("venda_detail");
    }

    public String editSetup() {
        return scalarSetup("venda_edit");
    }

    public String editVendaSetup() {
        return "venda_edit";
    }

    private String scalarSetup(String destination) {
        reset(false);
        venda = (Venda) JsfUtil.getObjectFromRequestParameter("jsfcrud.currentVenda", converter, null);
        if (venda == null) {
            String requestVendaString = JsfUtil.getRequestParameter("jsfcrud.currentVenda");
            JsfUtil.addErrorMessage("The venda with id " + requestVendaString + " no longer exists.");
            return relatedOrListOutcome();
        }
        return destination;
    }

    public String edit() {
        String vendaString = converter.getAsString(FacesContext.getCurrentInstance(), null, venda);
        String currentVendaString = JsfUtil.getRequestParameter("jsfcrud.currentVenda");
        if (vendaString == null || vendaString.length() == 0 || !vendaString.equals(currentVendaString)) {
            String outcome = editSetup();
            if ("venda_edit".equals(outcome)) {
                JsfUtil.addErrorMessage("Could not edit venda. Try again.");
            }
            return outcome;
        }
        try {
            jpaController.edit(venda);
            JsfUtil.addSuccessMessage("Venda was successfully updated.");
        } catch (IllegalOrphanException oe) {
            JsfUtil.addErrorMessages(oe.getMessages());
            return null;
        } catch (NonexistentEntityException ne) {
            JsfUtil.addErrorMessage(ne.getLocalizedMessage());
            return listSetup();
        } catch (Exception e) {
            JsfUtil.ensureAddErrorMessage(e, "A persistence error occurred.");
            return null;
        }
        return detailSetup();
    }

    public void calcularParcelas_txtJurosMes(ValueChangeEvent evt) {


        if (evt.getNewValue() instanceof Long) {
            Long l = (Long) evt.getNewValue();
            venda.setJurosMes(new Float(l.floatValue()));
        } else if (evt.getNewValue() instanceof Double) {
            Double l = (Double) evt.getNewValue();
            venda.setJurosMes(l.floatValue());
        } else {
            venda.setJurosMes((Float) evt.getNewValue());
        }
        calcularParcelas();
    }

    public void calcularParcelas_txtQtdParcelas(ValueChangeEvent evt) {
        setQtdParcelas((Integer) evt.getNewValue());
        calcularParcelas();
    }

    public String removerProdutoVenda() {
        String prodId = JsfUtil.getRequestParameter("jsfcrud.currentProduto");
        int prod = Integer.parseInt(prodId);

        List<ProdutoVenda> prodsVenda = venda.getProdutoVendaCollection();
        List<ProdutoVenda> prodsVendaNew = new ArrayList<ProdutoVenda>();
        for (int i = 0; i < prodsVenda.size(); i++) {
            ProdutoVenda produtoVenda = prodsVenda.get(i);
            if (produtoVenda.getProduto().getProdutoId().intValue() != prod) {
                prodsVendaNew.add(produtoVenda);
            }
        }
        if (prodsVendaNew.size() == 0) {
            prodsVendaNew = null;
            parcelaVenda = null;
            venda.setJurosMes(0f);
            qtdParcelas = 1;

        }
        venda.setProdutoVendaCollection(prodsVendaNew);
        calcularParcelas();
        return "venda_create";
    }

    public String removerOperacaoExtra() {
        String opEx = JsfUtil.getRequestParameter("jsfcrud.currentOpercaoExtra");
        int opExId = Integer.parseInt(opEx);

        List<OpercaoExtra> opercaoExtras = venda.getOpercaoExtraCollection();
        List<OpercaoExtra> opercaoExtrasNew = new ArrayList<OpercaoExtra>();
        for (int i = 0; i < opercaoExtras.size(); i++) {
            OpercaoExtra opercaoExtra = opercaoExtras.get(i);
            if (opercaoExtra.getOperacaoExtraTipoId().getOperacaoExtraTipoId().intValue() != opExId) {
                opercaoExtrasNew.add(opercaoExtra);
            }
        }

        venda.setOpercaoExtraCollection(opercaoExtrasNew);
        calcularParcelas();
        return "venda_create";
    }

    public String removerProdutoVendaEdit() {
        removerProdutoVenda();
        return "venda_edit";
    }

    public String calcularParcelas() {
        List<ProdutoVenda> produtosVendas = venda.getProdutoVendaCollection();

        venda.setTotalVenda(0f);

        if (produtosVendas == null || produtosVendas.size() == 0) {
            return "";
        }

        for (int i = 0; i < produtosVendas.size(); i++) {
            ProdutoVenda produtoVenda = produtosVendas.get(i);
            venda.setTotalVenda(venda.getTotalVenda() + produtoVenda.getPrecoUnitario() * produtoVenda.getQuantidade());
        }

        venda.setTotalVenda(venda.getTotalVenda() + venda.getValorTransporte());
        venda.setTotalVenda(venda.getTotalVenda() + venda.getSeguroTransporte());

        List<OpercaoExtra> opercaoExtras = venda.getOpercaoExtraCollection();
        if (opercaoExtras != null) {
            for (Iterator<OpercaoExtra> it = opercaoExtras.iterator(); it.hasNext();) {
                OpercaoExtra opercaoExtra = it.next();
                venda.setTotalVenda(venda.getTotalVenda() + opercaoExtra.getValor());
            }
        }
        float totalParcela = venda.getTotalVenda() / getQtdParcelas();
        if (venda.getJurosMes() > 0f && getQtdParcelas() > 1) {
            totalParcela += totalParcela * venda.getJurosMes() / 10;
        }

        venda.setTotalVenda(totalParcela * getQtdParcelas());

        parcelaVenda = new ArrayList<ParcelaVO>();

        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataPagamento());
        for (int i = 1; i <= getQtdParcelas(); i++) {
            if (i > 1) {
                cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
            }
            parcelaVenda.add(new ParcelaVO(i, totalParcela, cal.getTime(), getQtdParcelas()));
        }
        return "";
    }

    /**
     * @return the parcelaVenda
     */
    public List<ParcelaVO> getParcelaVenda() {
        return parcelaVenda;
    }

    /**
     * @param parcelaVenda the parcelaVenda to set
     */
    public void setParcelaVenda(List<ParcelaVO> parcelaVenda) {
        this.parcelaVenda = parcelaVenda;
    }

    /**
     * @return the qtdParcelas
     */
    public Integer getQtdParcelas() {
        return qtdParcelas;
    }

    /**
     * @param qtdParcelas the qtdParcelas to set
     */
    public void setQtdParcelas(Integer qtdParcelas) {
        this.qtdParcelas = qtdParcelas;
    }

    public String destroy() {
        String idAsString = JsfUtil.getRequestParameter("jsfcrud.currentVenda");
        Integer id = new Integer(idAsString);
        try {
            jpaController.destroy(id);
            JsfUtil.addSuccessMessage("Venda was successfully deleted.");
        } catch (IllegalOrphanException oe) {
            JsfUtil.addErrorMessages(oe.getMessages());
            return null;
        } catch (NonexistentEntityException ne) {
            JsfUtil.addErrorMessage(ne.getLocalizedMessage());
            return relatedOrListOutcome();
        } catch (Exception e) {
            JsfUtil.ensureAddErrorMessage(e, "A persistence error occurred.");
            return null;
        }

        return relatedOrListOutcome();
    }

    private String relatedOrListOutcome() {
        String relatedControllerOutcome = relatedControllerOutcome();
        if (relatedControllerOutcome != null) {
            return relatedControllerOutcome;
        }

        return listSetup();
    }

    public List<Venda> getVendaItems() {
        if (vendaItems == null) {
            getPagingInfo();
            vendaItems = jpaController.findVendaEntities(pagingInfo.getBatchSize(), pagingInfo.getFirstItem());
        }

        return vendaItems;
    }

    public String next() {
        reset(false);
        getPagingInfo().nextPage();
        return "venda_list";
    }

    public String prev() {
        reset(false);
        getPagingInfo().previousPage();
        return "venda_list";
    }

    private String relatedControllerOutcome() {
        String relatedControllerString = JsfUtil.getRequestParameter("jsfcrud.relatedController");
        String relatedControllerTypeString = JsfUtil.getRequestParameter("jsfcrud.relatedControllerType");
        if (relatedControllerString != null && relatedControllerTypeString != null) {
            FacesContext context = FacesContext.getCurrentInstance();
            Object relatedController = context.getApplication().getELResolver().getValue(context.getELContext(), null, relatedControllerString);
            try {
                Class<?> relatedControllerType = Class.forName(relatedControllerTypeString);
                Method detailSetupMethod = relatedControllerType.getMethod("detailSetup");
                return (String) detailSetupMethod.invoke(relatedController);
            } catch (ClassNotFoundException e) {
                throw new FacesException(e);
            } catch (NoSuchMethodException e) {
                throw new FacesException(e);
            } catch (IllegalAccessException e) {
                throw new FacesException(e);
            } catch (InvocationTargetException e) {
                throw new FacesException(e);
            }

        }
        return null;
    }

    private void reset(boolean resetFirstItem) {
        venda = null;
        vendaItems = null;
        pagingInfo.setItemCount(-1);
        if (resetFirstItem) {
            pagingInfo.setFirstItem(0);
        }
        isEditingVenda = false;

    }

    public void validateCreate(FacesContext facesContext, UIComponent component, Object value) {
        Venda newVenda = new Venda();
        String newVendaString = converter.getAsString(FacesContext.getCurrentInstance(), null, newVenda);
        String vendaString = converter.getAsString(FacesContext.getCurrentInstance(), null, venda);
        if (!newVendaString.equals(vendaString)) {
            createSetup();
        }

    }

    public Converter getConverter() {
        return converter;
    }

//DATA VENDA
    public int getFuncionarioDiaDataVenda() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataVenda());
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    public void setFuncionarioDiaDataVenda(int day) {
        venda.getDataVenda().setDate(day);
    }

    public int getFuncionarioMesDataVenda() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataVenda());
        return cal.get(Calendar.MONTH) + 1;
    }

    public void setFuncionarioMesDataVenda(int mes) {
        venda.getDataVenda().setMonth(mes - 1);
    }

    public int getFuncionarioAnoDataVenda() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataVenda());
        return cal.get(Calendar.YEAR);
    }

    public void setFuncionarioAnoDataVenda(int ano) {
        venda.getDataVenda().setYear(ano - 1900);
    }

// DATA ENTREGA
    public int getFuncionarioDiaDataEntrega() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataEntrega());
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    public void setFuncionarioDiaDataEntrega(int day) {
        venda.getDataEntrega().setDate(day);
    }

    public int getFuncionarioMesDataEntrega() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataEntrega());
        return cal.get(Calendar.MONTH) + 1;
    }

    public void setFuncionarioMesDataEntrega(int mes) {
        venda.getDataEntrega().setMonth(mes - 1);
    }

    public int getFuncionarioAnoDataEntrega() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataEntrega());
        return cal.get(Calendar.YEAR);
    }

    public void setFuncionarioAnoDataEntrega(int ano) {
        venda.getDataEntrega().setYear(ano - 1900);
    }

// DATA PAGAMENTO
    public int getFuncionarioDiaDataPagamento() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataPagamento());
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    public void setFuncionarioDiaDataPagamento(int day) {
        venda.getDataPagamento().setDate(day);
    }

    public int getFuncionarioMesDataPagamento() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataPagamento());
        return cal.get(Calendar.MONTH) + 1;
    }

    public void setFuncionarioMesDataPagamento(int mes) {
        venda.getDataPagamento().setMonth(mes - 1);
    }

    public int getFuncionarioAnoDataPagamento() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(venda.getDataPagamento());
        return cal.get(Calendar.YEAR);
    }

    public void setFuncionarioAnoDataPagamento(int ano) {
        venda.getDataPagamento().setYear(ano - 1900);
    }

    /**
     * @return the isEditingVenda
     */
    public Boolean getIsEditingVenda() {
        return isEditingVenda;
    }

    /**
     * @param isEditingVenda the isEditingVenda to set
     */
    public void setIsEditingVenda(Boolean isEditingVenda) {
        this.isEditingVenda = isEditingVenda;
    }
}
